import java.net.*;
import java.util.Vector;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
/**
 * Gemaakt door: Jeroen. Communicatie met domein: Jeroen
 * Communicatie met de view: Jesse
 * 
 */
public class Control implements WindowListener, ItemListener, ActionListener, FocusListener{
	private InetAddress[] addresses;
	private Server server;
	private GUI_Frame gui;
	private Thread serverThread;
	String t1, t2;
	boolean isRunning = false;
	
	  /**
	 * Constructor die alles opstart wat nodig is: 
	 * het zoekt alle beschikbare hosts op en zet deze in de array met ip's.
	 * Daarnaast wordt de output naar de AWT textarea gesluisd. 
	 */
	public Control(){
		
		try {
			InetAddress localhost = InetAddress.getLocalHost();
			addresses = InetAddress.getAllByName(localhost.getHostName());
			// zet array om naar Vector
			Vector<String> hosts = new Vector<String>();
			for (int i = 0; i < addresses.length; i++){
				hosts.add(i, addresses[i].toString());
				System.out.println(addresses[i].toString());
			
			
			
			}
			
			gui = new GUI_Frame(hosts, this);
			System.setOut(new PrintStream(new MyOutputStream(gui)));
			t1 = gui.t1.getText();
			t2 = gui.t2.getText();
			
			
		}catch (UnknownHostException uhe){
			
		}
	}

	
	public void windowActivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	
	public void windowClosed(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	public void windowClosing(WindowEvent arg0) {
		// TODO Auto-generated method stub
		stopServer();
		System.exit(0);
		
	}

	
	public void windowDeactivated(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	
	public void windowDeiconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	
	public void windowIconified(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	
	public void windowOpened(WindowEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	
	public void itemStateChanged(ItemEvent ie) 
	{
		switchSettings();		
	}
	public void focusLost(FocusEvent fe)
	{	
		if(t1.equals(gui.t1.getText()) && t2.equals(gui.t2.getText()))
		{
			
		}
		else
		{
			switchSettings();
		}
	}
	public void focusGained(FocusEvent fe)
	{
		t2 = gui.t2.getText();
		t1 = gui.t1.getText();
	}
	 /**
	 * Een boolean die voornamelijk controlleert of de server al gestart kan worden.
	 * gemaakt door jesse.
	 */
	public boolean checkForm()
	{
		if(gui.combobox.getItemCount() == 0)
		{	
			gui.setError("There's no host!");
			gui.validate();
			return false;
		}
		if(!(gui.t1.getText().matches("\\d{1,4}")))
		{	gui.setError("The port was not specified correctly");
			gui.validate();
			return false;
		}
		//to do: add a check for the location
		gui.setError("");
		gui.validate();
		return true;
		
	}
	 /**
	  * Gemaakt door Jeroen en jesse
	 * Deze methode voert als de form correct is de volgende taken uit:
	 *
	 * bij true start hij een server.
	 * bij false stopt hij de server. 
	 * Daarnaast kan hij ook de server starten 'realtime' zonder de knop van kleur te wijzigen
	 * @param a : dit is true als hij de server moet starten en false als hij de server
	 * moet stoppen.
	 * @param b : dit specificeert of hij de knoppen moet omwisselen.
	 */
	public void doStart(boolean a, boolean b)
	{	
		if(a) //start
		{	
			if(checkForm())
			{
				String i = gui.combobox.getSelectedItem();
				InetAddress adres = null;
				for(int j = 0; j<addresses.length; j++)
				{
					if(addresses[j].toString().equals(i))
					{
						adres = addresses[j];
					}
				}
				String port = gui.t1.getText();
				int portnumber = Integer.parseInt(port);
				String codebase = gui.t2.getText();
				try
				{	
					if(adres != null)
					{
						server = new Server(adres, portnumber, codebase);
						serverThread = new Thread(server);
						serverThread.start();
						System.out.println("\n== Server started ==\n");
						isRunning = true;
						if(b)
						{
							gui.flipButton();
						}
					}
				}
				catch(IOException ioe)
				{
					System.out.println("IO exception");
				}
			}
			
		}
		else if(!a) //stop
		{	
			if(b)
			{
				gui.flipButton();
			}
			stopServer();
			isRunning = false;
		}
		
	}
	/**
	 * gemaakt door Jesse
	 * Deze methode is voor het switchen van serversettings. Bij een focuslost wordt deze
	 * methode aangeroepen die vervolgens de doButton methode aanroept. Als de form tijdens het runnen van een server
	 * foutief wordt ingevuld, dan stopt de server.
	 * 
	 */
	public void switchSettings()
	{	
		if(isRunning)
		{
			if(checkForm())
			{	
				doStart(false, false);
				doStart(true, false);
			}
			else
			{
				doStart(false, true);
			}
		}
	}
	
	/**
	 * gemaakt door Jeroen
	 */
	public void actionPerformed(ActionEvent e) 
	{
		// start button is gedrukt start de server
		// server = new Server();
		if(e.getActionCommand().equals("Start"))
		{	
			doButton(true);
		}
		if(e.getActionCommand().equals("Stop"))
		{	
			doButton(false);
		}
	}
	public void doButton(boolean a)
	{
		if(a)
		{
			doStart(true, true);
		}
		else
		{
			doStart(false, true);
		}
		
	}
	 /**
	  * gemaakt door Jeroen
	 * Deze methode roept de custom method 'close' aan van Server. 
	 */
	private void stopServer(){
		try {
			server.close();
		}catch (SocketException sse){
			System.out.println("Socket Exception");
		}catch (IOException io){
			System.out.println("IO Exception");
		}
		catch(NullPointerException ne)
		{
			
		}
	}
}
